<template>
    <view class="numbox">
        <view @click="_calcValue('minus')" class="numbox-minus numbox-btns" :style="{background}">
            <text class="numbox-text" :class="{ 'numbox-disabled': status.inputValue <= min || disabled }"
                :style="{ color }">-</text>
        </view>
        <input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="numbox-value" type="number"
            v-model="status.inputValue" :style="{ background, color }" />
        <view @click="_calcValue('plus')" class="numbox-plus numbox-btns" :style="{ background }">
            <text class="numbox-text" :class="{ 'numbox-disabled': status.inputValue >= max || disabled }"
                :style="{ color }">+</text>
        </view>
    </view>
</template>

<script setup lang='ts' name="AppInputNumber">
/**
 * InputNumber 数字输入框
 * @description 带加减按钮的数字输入框
 * @tutorial https://ext.dcloud.net.cn/plugin?id=31
 * @property {Number} modelValue 输入框当前值
 * @property {Number} min 最小值
 * @property {Number} max 最大值
 * @property {Number} step 每次点击改变的间隔大小
 * @property {String} background 背景色
 * @property {String} color 字体颜色（前景色）
 * @property {Boolean} disabled = [true|false] 是否为禁用状态
 * @event {Function} change 输入框值改变时触发的事件，参数为输入框当前的 value
 * @event {Function} focus 输入框聚焦时触发的事件，参数为 event 对象
 * @event {Function} blur 输入框失焦时触发的事件，参数为 event 对象
 */
export interface AppInputNumberProps {
    modelValue?: number | string
    min?: number
    max?: number
    step?: number
    background?: string
    color?: string
    disabled?: boolean
}
export interface AppInputNumberEmits {
    (e: 'update:modelValue', value: AppInputNumberProps['modelValue']): void
    (e: 'change', value: AppInputNumberProps['modelValue']): void
    (e: 'input', value: AppInputNumberProps['modelValue']): void
    (e: 'blur', el: FocusEvent): void
    (e: 'focus', el: FocusEvent): void
}

const props = withDefaults(defineProps<AppInputNumberProps>(), {
    modelValue: 1,
    min: 0,
    max: 100,
    step: 1,
    background: '#f5f5f5',
    color: '#333',
    disabled: false
})
const emit = defineEmits<AppInputNumberEmits>()

const status = reactive({
    inputValue: 0,
})

onMounted(() => {
    status.inputValue = +props.modelValue
})

watch(() => props.modelValue, (val) => {
    status.inputValue = +val;
})

const _calcValue = (type: 'minus' | 'plus') => {
    if (props.disabled) {
        return;
    }
    const scale = _getDecimalScale();
    let value = status.inputValue * scale;
    let step = props.step * scale;
    if (type === "minus") {
        value -= step;
        if (value < (props.min * scale)) {
            return;
        }
        if (value > (props.max * scale)) {
            value = props.max * scale
        }
    }

    if (type === "plus") {
        value += step;
        if (value > (props.max * scale)) {
            return;
        }
        if (value < (props.min * scale)) {
            value = props.min * scale
        }
    }
    status.inputValue = +((value / scale).toFixed(String(scale).length - 1));
    emit("change", +status.inputValue);
    emit("update:modelValue", +status.inputValue);
}
const _getDecimalScale = () => {
    let scale = 1;
    if (~~props.step !== props.step) {
        scale = Math.pow(10, String(props.step).split(".")[1].length);
    }
    return scale;
}
const _onBlur = (event: FocusEvent) => {
    emit('blur', event)
    const tmpValue = (event.target as HTMLInputElement).value;
    // const tmpValue = (event.detail as any).value as string;
    if (!tmpValue) {
        return;
    }
    let value = +tmpValue;
    if (value > props.max) {
        value = props.max;
    } else if (value < props.min) {
        value = props.min;
    }
    const scale = _getDecimalScale();
    status.inputValue = Number(value.toFixed(String(scale).length - 1));
    emit('change', +status.inputValue);
    emit('input', +status.inputValue);
}
const _onFocus = (event: FocusEvent) => {
    emit('focus', event)
}
</script>

<style lang="scss" scoped>
$box-height: 26px;
$bg: #f5f5f5;
$br: 2px;
$color: #333;

.numbox {
    display: flex;
    flex-direction: row;
}

.numbox-btns {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    padding: 0 8px;
    background-color: $bg;
    /* #ifdef H5 */
    cursor: pointer;
    /* #endif */
}

.numbox-value {
    margin: 0 2px;
    background-color: $bg;
    width: 40px;
    height: $box-height;
    text-align: center;
    font-size: 14px;
    border-left-width: 0;
    border-right-width: 0;
    color: $color;
}

.numbox-minus {
    border-top-left-radius: $br;
    border-bottom-left-radius: $br;
}

.numbox-plus {
    border-top-right-radius: $br;
    border-bottom-right-radius: $br;
}

.numbox-text {
    line-height: 20px;
    font-size: 20px;
    font-weight: 300;
    color: $color;
}

.numbox .numbox-disabled {
    color: #c0c0c0 !important;
    /* #ifdef H5 */
    cursor: not-allowed;
    /* #endif */
}
</style>